import React, {
    PureComponent
} from 'react';

import {
    View,
    Text,
    FlatList,
    StyleSheet,
    ActivityIndicator
} from 'react-native';

import {
    MessageItem
} from './types';

export interface Props {
    userId: number,
    list: Array<MessageItem>,
    onLoadPage: Function,
    onReSend: Function,
    onAvatarClick: Function
}

interface State {
    refreshing?: boolean
}

import MsgRow from './msgRow';

const _await = (delay?: number) => (
    new Promise(resolve => {
        setTimeout(resolve, delay)
    })
)

class Message extends PureComponent<Props|any, State> {
    private moveY: number = 0;
    private scroll: any = null;

    static defaultProps = {
        userId: 0,
        list: [],
        onLoadPage: () => null
    }

    state = {
        refreshing: false
    }

    private _renderItem = ({item}:any) => {
        const {
            userId,
            onReSend,
            onAvatarClick
        } = this.props;
        return (
            <MsgRow
                data={item}
                userId={userId}
                onReSend={onReSend}
                onAvatarClick={onAvatarClick}
            />
        )
    }

    get inverted() {
        const {
            list
        } = this.props;
        const {
            length
        } = list;
        return length > 10
    }

    get dataList() {
        const {
            list = []
        } = this.props;

        const _list = [...list];

        const _map = (item:any, i:number) => ({
            ...item,
            key: `msg_row_key_${i}`
        })

        const __list = (
            this.inverted ?
                _list.reverse() : _list
        )
        return __list.map(_map);
    }

    get refreshing() {
        const {
            refreshing
        } = this.state;
        return this.inverted ?
            undefined : refreshing;
    }

    get _renderTopLoading() {
        const {
            refreshing
        } = this.state;

        return refreshing ? (
            <View style={styles.listFooter}>
                <ActivityIndicator
                    color="#ececec"
                />
                <Text style={styles.loadingText}>
                    Loading...
                </Text>
            </View>
        ) : null;
    }

    private _onScroll = ({nativeEvent}:any) => {
        const {
            contentSize,
            contentOffset,
            layoutMeasurement
        } = nativeEvent;

        const {
            y
        } = contentOffset;

        const {
            height
        } = layoutMeasurement;

        const offsetY = (
            contentSize.height - height
        )

        const direction = (
            this.moveY - y < 0 ? `down` : `up`
        )

        if (direction === `down` && y > 0) {
            this._checkPullDown(offsetY, y);
        }

        this.moveY = y;
    }

    private _checkPullDown = (offsetY:number, y:number) => {
        if (offsetY < 0) {
            return this._onRefresh()
        }
        if (offsetY <= y + 50) {
            return this._onRefresh()
        }
    }

    private _onRefresh = async () => {
        const {
            refreshing
        } = this.state;

        const {
            onLoadPage
        } = this.props;

        if (refreshing) {
            return false
        }

        this.setState({
            refreshing: true
        })

        onLoadPage(this._onRefreshEnd)
    }

    private _onRefreshEnd = () => {
        this.setState({
            refreshing: false
        })
    }

    public scrollToEnd = async () => {
        await _await(300);
        if(!this.scroll) {
            return false
        }
        if (this.inverted) {
            this.scroll.
            scrollToIndex({
                index: 0
            })
        }
        else {
            this.scroll.
            scrollToEnd({
                animated: true
            })
        }
    }

    render() {
        return (
            <View style={styles.container}>
                <FlatList
                    data={this.dataList}
                    inverted={this.inverted}
                    ref={e => this.scroll = e}
                    refreshing={this.refreshing}
                    renderItem={this._renderItem}
                    onScroll={this.inverted ? this._onScroll : undefined}
                    onRefresh={this.inverted ? undefined : this._onRefresh}
                    ListFooterComponent={this.inverted ? this._renderTopLoading : undefined}
                />
            </View>
        )
    }
}

export default Message;


const styles = StyleSheet.create({
    container: {
        flex: 1
    },
    listFooter: {
        alignItems: `center`,
        flexDirection: `row`,
        justifyContent: `center`,
        paddingVertical: 16
    },
    loadingText: {
        fontSize: 14,
        color: `#f2f2f2`,
        paddingLeft: 8
    },
}) as any;